<?php

namespace App\Kuafu\Bak\Command;

use App\Library\FeiShu\SendFs;
use Illuminate\Console\Command;
use Kuafu\GeneralFs\BuildFs;

class BakOrderMonthCommand extends Command
{
    protected $signature = 'bak:order-month {bakMonth}';

    protected $description = '每月备份';

    private string $filePath;

    public function handle()
    {
        $bakMonth = (string)$this->argument('bakMonth'); // 202301
        if (!$bakMonth) {
            dd('请输入备份月份');
        }

        $this->do($bakMonth);
    }

    public function do(string $bakMonth)
    {
        $startSeconds = time();

        // 设置备份路径
        if (config('app.env') == 'dev') {
            $this->filePath = "~/Downloads/rds/month/{$bakMonth}";
        } else {
            $this->filePath = "/mnt/backup/rds/month/{$bakMonth}";
        }

        exec("mkdir -p {$this->filePath}");

        // 备份
        $bakTables = static::getBakTables();
        foreach ($bakTables as $db => $tables) {
            dump("开始备份{$db}库");

            foreach ($tables as $table) {
                dump("开始备份{$table}");
                $this->bak($db, $table, $bakMonth);
            }
        }

        dump('结束备份');

        // 压缩
        exec("7za a -mx9 /mnt/backup/rds/month/{$bakMonth}.7z /mnt/backup/rds/month/{$bakMonth}");

        // 删除文件夹
        exec("rm -rf /mnt/backup/rds/month/{$bakMonth}");

        $useSeconds = time() - $startSeconds;

        // 发送消息通知
        BuildFs::newRobot(SendFs::ROBOT_FS_YW_MONITOR)
               ->setTitleContent('订单表每月备份执行完成', "目录：{$this->filePath}\n\n 执行耗时：{$useSeconds}秒")
               ->send();
    }

    /**
     * 备份
     * @param string $db
     * @param string $table
     * @param string $bakMonth
     * @return void
     */
    private function bak(string $db, string $table, string $bakMonth)
    {
        $dbConfig = config("database.connections.{$db}");

        $host     = $dbConfig['host'];
        $port     = $dbConfig['port'];
        $username = $dbConfig['username'];
        $password = $dbConfig['password'];
        $database = $dbConfig['database'];
        $prefix   = $dbConfig['prefix'];

        for ($i = 0; $i <= 99; $i++) {
            $tableName = $table . str_pad($i, 3, 0, STR_PAD_LEFT);

            // start/endTime
            $startTime = strtotime($bakMonth . '01');
            $endTime   = strtotime("+1 month {$bakMonth}01");

            // mysqldump
            $fileName   = "{$tableName}.sql";
            $resultCode = null;
            $output     = "";
            exec("mysqldump -h{$host} -P{$port} -u{$username} -p{$password} --add-locks=0 --no-create-info --single-transaction {$database} {$tableName} --where=\"createdAt>={$startTime} and createdAt < {$endTime}\"  > {$this->filePath}/{$fileName}",
                $output, $resultCode);

            // mysqldump - error
            if ($resultCode !== 0) {
                dump("{$tableName} bakMonth:{$bakMonth} mysqldump error...");
            }

            usleep(10000);
        }
    }

    public static function getBakTables(): array
    {
        return [
            'mysqlOrder'  => [
                'kf_order_',
                'kf_order_detail_',
                'kf_order_coupon_',
                'kf_order_coupon_external_',
                'kf_order_discount_',
                'kf_order_external_',
                'kf_order_pay_union_',
                'kf_order_user_info_',
                'kf_pay_stream_',
            ],
            'mysqlWaiMai' => [
                'kf_waimai_orders_',
                'kf_waimai_order_details_',
                'kf_waimai_part_refund_logs_',
            ],
        ];
    }
}
